/**
 * 玩家数据访问对象
 * 提供玩家数据的CRUD操作
 */
import { Player } from '../entity/Player';
import fs from '@ohos.file.fs';
import { BusinessError } from '@ohos.base';

export class PlayerDAO {
  // 数据文件路径
  private static readonly PLAYERS_FILE: string = `${this.getDataDir()}/players.json`;
  
  /**
   * 获取数据存储目录
   * @returns 数据存储目录路径
   */
  private static getDataDir(): string {
    // 在实际应用中，应该使用Context获取应用的data目录
    // 这里使用与JSONDataService相同的模拟路径
    return '/data/storage/el2/base/ai_detective';
  }
  
  /**
   * 确保数据目录和文件存在
   */
  private static async ensureDataReady(): Promise<void> {
    try {
      // 确保目录存在
      try {
        await fs.access(this.getDataDir());
      } catch (error) {
        if ((error as BusinessError).code === 20) {
          await fs.mkdir(this.getDataDir(), 0o777, true);
          console.log(`创建玩家数据目录: ${this.getDataDir()}`);
        } else {
          throw error;
        }
      }
      
      // 确保文件存在
      try {
        await fs.access(this.PLAYERS_FILE);
      } catch (error) {
        if ((error as BusinessError).code === 20) {
          console.log(`创建玩家数据文件: ${this.PLAYERS_FILE}`);
          const file = await fs.open(this.PLAYERS_FILE, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
          try {
            await fs.write(file.fd, JSON.stringify([], null, 2));
          } finally {
            await fs.close(file);
          }
        } else {
          throw error;
        }
      }
    } catch (error) {
      console.error('准备玩家数据失败:', error);
      throw error;
    }
  }
  
  /**
   * 读取玩家数据文件
   * @returns 玩家数据数组
   */
  private static async readPlayersFile(): Promise<any[]> {
    try {
      await this.ensureDataReady();
      
      const file = await fs.open(this.PLAYERS_FILE, fs.OpenMode.READ_ONLY);
      try {
        const fileInfo = await fs.stat(this.PLAYERS_FILE);
        
        if (fileInfo.size === 0) {
          return [];
        }
        
        const buffer = new ArrayBuffer(fileInfo.size);
        await fs.read(file.fd, buffer, { offset: 0, length: fileInfo.size });
        
        const decoder = new TextDecoder('utf-8');
        const jsonString = decoder.decode(new Uint8Array(buffer));
        
        return JSON.parse(jsonString);
      } finally {
        await fs.close(file);
      }
    } catch (error) {
      console.error('读取玩家文件失败:', error);
      return [];
    }
  }
  
  /**
   * 写入玩家数据文件
   * @param players 玩家数据数组
   */
  private static async writePlayersFile(players: any[]): Promise<void> {
    try {
      await this.ensureDataReady();
      
      const jsonString = JSON.stringify(players, (key, value) => {
        if (value instanceof Date) {
          return value.toISOString();
        }
        return value;
      }, 2);
      
      const file = await fs.open(this.PLAYERS_FILE, fs.OpenMode.READ_WRITE | fs.OpenMode.TRUNCATE | fs.OpenMode.CREATE);
      try {
        await fs.write(file.fd, jsonString);
      } finally {
        await fs.close(file);
      }
    } catch (error) {
      console.error('写入玩家文件失败:', error);
      throw error;
    }
  }
  
  /**
   * 获取所有玩家
   * @returns 玩家列表
   */
  public static async getAllPlayers(): Promise<Player[]> {
    try {
      const playersData = await this.readPlayersFile();
      return playersData.map((p: any) => Player.fromJSON(p));
    } catch (error) {
      console.error('获取所有玩家失败:', error);
      return [];
    }
  }
  
  /**
   * 根据ID获取玩家
   * @param id 玩家ID
   * @returns 玩家对象或null
   */
  public static async getPlayerById(id: string): Promise<Player | null> {
    try {
      const playersData = await this.readPlayersFile();
      const playerData = playersData.find((p: any) => p.id === id);
      return playerData ? Player.fromJSON(playerData) : null;
    } catch (error) {
      console.error(`根据ID获取玩家失败 (${id}):`, error);
      return null;
    }
  }
  
  /**
   * 根据名称获取玩家
   * @param name 玩家名称
   * @returns 玩家对象或null
   */
  public static async getPlayerByName(name: string): Promise<Player | null> {
    try {
      const playersData = await this.readPlayersFile();
      const playerData = playersData.find((p: any) => p.name === name);
      return playerData ? Player.fromJSON(playerData) : null;
    } catch (error) {
      console.error(`根据名称获取玩家失败 (${name}):`, error);
      return null;
    }
  }
  
  /**
   * 创建玩家
   * @param player 玩家对象
   * @returns 创建的玩家
   */
  public static async createPlayer(player: Player): Promise<Player> {
    try {
      // 检查玩家名称是否已存在
      const existingPlayer = await this.getPlayerByName(player.name);
      if (existingPlayer) {
        throw new Error(`玩家名称 "${player.name}" 已存在`);
      }
      
      const playersData = await this.readPlayersFile();
      playersData.push(player.toJSON());
      await this.writePlayersFile(playersData);
      
      console.log(`玩家创建成功: ${player.name} (ID: ${player.id})`);
      return player;
    } catch (error) {
      console.error('创建玩家失败:', error);
      throw error;
    }
  }
  
  /**
   * 更新玩家
   * @param player 玩家对象
   * @returns 更新后的玩家
   */
  public static async updatePlayer(player: Player): Promise<Player> {
    try {
      const playersData = await this.readPlayersFile();
      const index = playersData.findIndex((p: any) => p.id === player.id);
      
      if (index !== -1) {
        // 确保名称不重复（如果修改了名称）
        const nameChanged = playersData[index].name !== player.name;
        if (nameChanged) {
          const nameExists = playersData.some((p: any) => p.id !== player.id && p.name === player.name);
          if (nameExists) {
            throw new Error(`玩家名称 "${player.name}" 已存在`);
          }
        }
        
        playersData[index] = player.toJSON();
        await this.writePlayersFile(playersData);
        console.log(`玩家更新成功: ${player.name} (ID: ${player.id})`);
      } else {
        throw new Error(`未找到要更新的玩家: ${player.id}`);
      }
      
      return player;
    } catch (error) {
      console.error('更新玩家失败:', error);
      throw error;
    }
  }
  
  /**
   * 删除玩家
   * @param id 玩家ID
   * @returns 是否删除成功
   */
  public static async deletePlayer(id: string): Promise<boolean> {
    try {
      const playersData = await this.readPlayersFile();
      const filteredPlayers = playersData.filter((p: any) => p.id !== id);
      
      if (filteredPlayers.length !== playersData.length) {
        await this.writePlayersFile(filteredPlayers);
        console.log(`玩家删除成功: ${id}`);
        return true;
      }
      
      console.warn(`未找到要删除的玩家: ${id}`);
      return false;
    } catch (error) {
      console.error('删除玩家失败:', error);
      return false;
    }
  }
  
  /**
   * 获取玩家排名（按积分排序）
   * @param limit 返回数量限制
   * @returns 玩家排名列表
   */
  public static async getPlayerRanking(limit: number = 10): Promise<Player[]> {
    try {
      const players = await this.getAllPlayers();
      return players
        .sort((a, b) => b.points - a.points)
        .slice(0, limit);
    } catch (error) {
      console.error('获取玩家排名失败:', error);
      return [];
    }
  }
  
  /**
   * 获取在线玩家（最近1小时内活跃）
   * @returns 在线玩家列表
   */
  public static async getOnlinePlayers(): Promise<Player[]> {
    try {
      const players = await this.getAllPlayers();
      const oneHourAgo = new Date();
      oneHourAgo.setHours(oneHourAgo.getHours() - 1);
      
      return players.filter(player => 
        new Date(player.lastOnlineAt) > oneHourAgo
      );
    } catch (error) {
      console.error('获取在线玩家失败:', error);
      return [];
    }
  }
}